from datetime import datetime, timedelta
from typing import Optional
import jwt
from passlib.context import CryptContext
from fastapi import HTTPException, status, Depends
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from sqlalchemy.orm import Session

from database import get_db
from db_models import UserDB
from models import User, UserRole

# JWT配置
SECRET_KEY = "your-secret-key-here-change-in-production"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30

# 密码加密上下文
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")

# HTTP Bearer 令牌验证
security = HTTPBearer()

def verify_password(plain_password: str, hashed_password: str) -> bool:
    """验证密码"""
    return pwd_context.verify(plain_password, hashed_password)

def get_password_hash(password: str) -> str:
    """生成密码哈希"""
    return pwd_context.hash(password)

def create_access_token(data: dict, expires_delta: Optional[timedelta] = None):
    """创建访问令牌"""
    to_encode = data.copy()
    if expires_delta:
        expire = datetime.utcnow() + expires_delta
    else:
        expire = datetime.utcnow() + timedelta(minutes=15)
    to_encode.update({"exp": expire})
    encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
    return encoded_jwt

def authenticate_user(db: Session, username: str, password: str) -> Optional[UserDB]:
    """验证用户凭据"""
    user = db.query(UserDB).filter(UserDB.username == username).first()
    if not user:
        return None
    if not verify_password(password, user.password_hash):
        return None
    return user

def get_user_by_username(db: Session, username: str) -> Optional[UserDB]:
    """根据用户名获取用户"""
    return db.query(UserDB).filter(UserDB.username == username).first()

def create_user(db: Session, username: str, password: str, role: UserRole = UserRole.USER) -> UserDB:
    """创建新用户"""
    password_hash = get_password_hash(password)
    db_user = UserDB(username=username, password_hash=password_hash, role=role)
    db.add(db_user)
    db.commit()
    db.refresh(db_user)
    return db_user

def get_current_user(
    credentials: HTTPAuthorizationCredentials = Depends(security),
    db: Session = Depends(get_db)
) -> UserDB:
    """获取当前用户（从JWT令牌）"""
    credentials_exception = HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="无效的认证凭据",
        headers={"WWW-Authenticate": "Bearer"},
    )
    
    try:
        payload = jwt.decode(credentials.credentials, SECRET_KEY, algorithms=[ALGORITHM])
        username: str = payload.get("sub")
        if username is None:
            raise credentials_exception
    except jwt.InvalidTokenError:
        raise credentials_exception
    
    user = get_user_by_username(db, username)
    if user is None:
        raise credentials_exception
    return user

def init_default_users(db: Session):
    """初始化默认用户"""
    # 检查是否已存在用户
    existing_users = db.query(UserDB).count()
    if existing_users > 0:
        return
    
    # 创建管理员用户
    create_user(db, "admin", "admin123", UserRole.ADMIN)
    
    # 创建两个默认用户
    default_users = [
        {"username": "zgy", "password": "0110"},
        {"username": "hjb", "password": "0926"}
    ]
    
    for user_data in default_users:
        create_user(db, user_data["username"], user_data["password"])
    
    print("✅ 默认用户创建完成")

def get_current_admin(
    current_user: UserDB = Depends(get_current_user)
) -> UserDB:
    """获取当前管理员用户（检查管理员权限）"""
    if current_user.role != UserRole.ADMIN:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="需要管理员权限才能访问此资源"
        )
    return current_user

def require_admin_or_self(
    target_user_id: int,
    current_user: UserDB = Depends(get_current_user)
) -> UserDB:
    """检查用户是否为管理员或者是目标用户本人"""
    if current_user.role != UserRole.ADMIN and current_user.id != target_user_id:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="没有权限访问该用户的数据"
        )
    return current_user